package ar.com.larreta.persistencia;

import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.SimpleExpression;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import ar.com.larreta.entidades.Entidad;

//FIXME: Revisar luego si es posible actualizar las fechas de creacion y modificacion de manera automatica con annotations (@prepersist, @preupdate o con listeners)
public class Dao extends HibernateDaoSupport {

	public static final String FROM = " FROM ";
	public static final String WHERE = " WHERE ";
	public static final String ORDER_BY = " ORDER BY ";
	public static final String ESPACIO = " ";
	public static final String SELECT_COUNT = "SELECT COUNT(*) ";


	/**
	 * existe
	 * @param clase
	 * @param id
	 * @return
	 */
	public Boolean existe(Class clase, Serializable id) {
		return (obtener(clase, id)!=null);
	}
	
	/**
	 * Obtener
	 * @param clase
	 * @param id
	 * @return
	 */
	public Entidad obtener(Class clase, Serializable id) {
		return (Entidad) getHibernateTemplate().get(clase, id);
	}
	
	
	/**
	 * Graba
	 * @param objeto
	 */
	public void grabar(Entidad entidad) {
		if (entidad.getFechaCreacion()==null){
			entidad.setFechaCreacion(new Date());
		}
		getHibernateTemplate().save(entidad);
	}
	
	/**
	 * Actualiza
	 * @param objeto
	 */
	public void actualizar(Entidad entidad) {
		entidad.setFechaUltimaModificacion(new Date());
		getHibernateTemplate().update(entidad);
	}

	/**
	 * Borra
	 * @param objeto
	 */
	public void borrar(Object objeto) {
		getHibernateTemplate().delete(objeto);
	}

	/**
	 * Borra todos
	 * @param objeto
	 */
	public void borrarTodos(Collection objetos) {
		getHibernateTemplate().deleteAll(objetos);
	}
	
	
	/**
	 * Lista
	 * @param clase
	 * @return
	 */
	public List listar(Criteria criteria){
		return criteria.list();
	}

	/**
	 * Contar
	 * @param criteria
	 * @return
	 */
	public Integer contar(Criteria criteria){
		criteria.setProjection(Projections.rowCount());
		return (Integer)criteria.uniqueResult();
	}	

	
	/**
	 * Generar Criteria con Alias
	 * @param clase
	 * @param primerResultado
	 * @param maxResultados
	 * @param order
	 * @param condiciones
	 * @return
	 */
	public Criteria getCriteria(String alias, Class clase, Integer primerResultado, Integer maxResultados, Order order, List<SimpleExpression> condiciones) {
		Criteria criteria = getSession().createCriteria(clase, alias);
		
		getCriteria(primerResultado, maxResultados, order, condiciones, criteria);
		
		return criteria;
	}
	
	/**
	 * Generar Criteria
	 * @param clase
	 * @param primerResultado
	 * @param maxResultados
	 * @param order
	 * @param condiciones
	 * @return
	 */
	public Criteria getCriteria(Class clase, Integer primerResultado, Integer maxResultados, Order order, List<SimpleExpression> condiciones) {
		Criteria criteria = getSession().createCriteria(clase);
		
		getCriteria(primerResultado, maxResultados, order, condiciones, criteria);
		
		return criteria;
	}

	/**
	 * A partir del criteria pasado como parametro le setea cual es el primer resultado, la maxima cantidad de resultados, el orden y las condiciones
	 * @param primerResultado
	 * @param maxResultados
	 * @param order
	 * @param condiciones
	 * @param criteria
	 */
	public void getCriteria(Integer primerResultado, Integer maxResultados,	Order order, List<SimpleExpression> condiciones, Criteria criteria) {
		if (primerResultado!=null){
			criteria.setFirstResult(primerResultado);
		}
		
		if (maxResultados!=null){
			criteria.setMaxResults(maxResultados);
		}
		
		if (order!=null){
			criteria.addOrder(order);
		}
		if (condiciones!=null){
			Iterator<SimpleExpression> iterator = condiciones.iterator();
			while (iterator.hasNext()) {
				SimpleExpression simpleExpression = (SimpleExpression) iterator.next();
				criteria.add(simpleExpression);
			}
		}
	}
	
}
